#########################################################################
# Time-stamp: <04/09/23 10:25:27 ostolop>
#########################################################################
package EP::EPC::Core::Data_Viewer;

use strict;

use EP::Config;
use EP::Common;
use EP::Common::General;

use EP::EPC::Core;
use EP::EPC::Core::Component;

use EP::Visualization::Grid;
use EP::Visualization::Hooks;
use EP::Visualization::HeatmapGraphic;
use EP::Visualization::LineGraphic;
use EP::Visualization::TreeGraphic;
use EP::Visualization::AnnotationGraphic;
use EP::Visualization::Collapser;

use CGI qw/:standard/;
use Storable;

our @ISA = qw ( EP::EPC::Core::Component );

sub process_component {
  my $self = shift;

  my ($process_result, $svg_file, $width, $height) = $self->process_data_viewer ();

  if ( not ref ( $process_result ) ) {
    $process_result = { visualization  => "$EP::Config::h->{HTML_HREF}/$EP::Config::h->{WWW_TMP}/$svg_file",
			visualization_width => $width,
			visualization_height => $height,
			src_dataset_id => $self->{src_dataset}->id,
			dst_dataset_id => $self->{src_dataset}->id
		      };
  }

  $self->{CD}->{process_result} = $process_result;
  return OK;
}

sub process_data_viewer {
  my $self = shift;

  if ( $self->{query}->param ( "action" ) =~ /display_action:(.*)/ ) {
    my $action = retrieve EP::Common::DBI::Action ( $1 );
    my $action_metadata = $action->metadata;
    my $process_result = $action_metadata->{process_result};

    return ( $process_result );
  }

  my $result;
  my $svg_file;
  my $width;
  my $height;

  $self->{session}->status ( "Processing ..." );

  $_ = $self->{src_dataset}->type;

 SWITCH: {
    /exp/
      && do {
	($result, $svg_file, $width, $height) = $self->create_visualization();
	last SWITCH;
      };
    /seq/
      && do {
	last SWITCH;
      };
  }

  return ($result, $svg_file, $width, $height);
}

sub create_visualization {
  my $self = shift;

  my $dataset = $self->{src_dataset};

  $self->{session}->status ( "Running visualization ..." );

  my @v_hooks = sort { $a <=> $b} keys %{$dataset->data->rows};
  my @h_hooks = sort { $a <=> $b} keys %{$dataset->data->cols};

  my $v_hookset = new EP::Visualization::Hooks ( \@v_hooks );
  my $h_hookset = new EP::Visualization::Hooks ( \@h_hooks );

  # initialize cell sizes to small
  my ($cell_height, $cell_width ) = ( 2, 2 );

  if ( scalar @v_hooks < 200 ) {
    $cell_height = 12;
  } elsif ( scalar @v_hooks < 500 ) {
    $cell_height = 6;
  }

  if ( scalar @h_hooks < 200 ) {
    $cell_width = 12;
  } elsif ( scalar @h_hooks < 500 ) {
    $cell_width = 6;
  }

  #create heatmap
  my $heatmap = new EP::Visualization::HeatmapGraphic ( data => $dataset->data->raw_data, cell_height => $cell_height, cell_width => $cell_width, interactive => 1 );
  $heatmap->setVerticalHookSet   ( $v_hookset );
  $heatmap->setHorizontalHookSet ( $h_hookset );

  #create annotation
  my $row_annotate = $dataset->data->rows;
  my @row_annots;
  push @row_annots, $row_annotate->{$_} foreach sort { $a <=> $b} keys %{$dataset->data->rows};

  my $row_annotation = new EP::Visualization::AnnotationGraphic ( data => \@row_annots, 'font-size' => $cell_height );
  $row_annotation->setHook ( $v_hookset );

  my $col_annotate = $dataset->data->cols;
  my @col_annots;
  push @col_annots, $col_annotate->{$_} foreach sort { $a <=> $b} keys %{$dataset->data->cols};

  my $col_annotation = new EP::Visualization::AnnotationGraphic ( data => \@col_annots, 'font-size' => $cell_width );
  $col_annotation->setHook ( $h_hookset );
  $col_annotation->setOrientation(-90);

  my $grid = new EP::Visualization::Grid ( 2, 2 );

  $grid->fillCellArray ( [
			  [ undef,           $col_annotation ],
			  [ $row_annotation, $heatmap        ]
			 ]
		       );

  die "Failed to generate visualization!" if not defined $grid;

  my $vis_format = $self->{current_user}->visualization_format;

  my $svg_output = "vis.$dataset.$$.svg";
  my $vis_output_filename = "vis.$dataset.$$." . ( $vis_format == 1 ? "png"  : "svg"  );

  open  ( SVG,">$EP::Config::h->{TMP}/$svg_output" );
  print SVG $grid->to_svg ();
  close ( SVG );

  if ( $vis_format == 1 ) {
    # convert to PNG
  }

  my $HTML_OUTPUT;
  $HTML_OUTPUT .= table ( {-border => 0, -align=>"center", -width=>"100%"},
			  caption(''),
			  Tr ( { -align => "CENTER", -valign => "TOP" },
			       [
				td (
				    { -style => "border: thin solid black; padding: 2px" },
				    div (
					 { -style => "overflow:auto; height:500; width:100%" },
					 # 0 - SVG, 1 - PNG
					 ( $vis_format == 0 ) ?
					 svg_html ( $vis_output_filename, $grid->getGridWidth(), $grid->getGridHeight() ) :
					 img ( { -src => "$EP::Config::h->{HTML_HREF}/$EP::Config::h->{WWW_TMP}/$vis_output_filename" } )
					)
				   )
			       ]
			     )
			);

  return ( body ( { -bgcolor => "white" },
		  $HTML_OUTPUT ),
	   $vis_output_filename,
	   $grid->getGridWidth() < 600 ? 580 : $grid->getGridWidth(),
	   $grid->getGridHeight() );
}

sub svg_html {
  my ($svg_file, $width, $height) = @_;
  my $svg_html = <<__SVG_APPLET__;
    <EMBED ALIGN="center" SRC="$EP::Config::h->{HTML_HREF}/$EP::Config::h->{WWW_TMP}/$svg_file" NAME="SVGEmbed" HEIGHT="$height" WIDTH="$width" TYPE="image/svg-xml" PLUGINSPAGE="http://www.adobe.com/svg/viewer/install/">
__SVG_APPLET__

  return $svg_html;
}

1;
